package handler

import (
	dblayer "filestore-server/db"
	"filestore-server/util"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

const (
	// 密码加盐值
	pwdSalt   = "#890"
	tokenSalt = "_tokensalt"
)

// SignupHandler 处理用户注册请求
func SignupHandler(c *gin.Context) {
	c.Redirect(http.StatusFound, "http://"+c.Request.Host+"/static/view/signup.html")
}

// DoSignupHandler : 处理用户注册请求
func DoSignupHandler(c *gin.Context) {
	username := c.Request.FormValue("username")
	passwd := c.Request.FormValue("password")

	if len(username) < 3 || len(passwd) < 5 {
		c.JSON(http.StatusOK,
			gin.H{
				"msg": "Invalid parameter",
			})
		return
	}

	// 3.用户密码加盐处理
	encPasswd := util.Sha1([]byte(pwdSalt + passwd))
	// 4.存入数据库 tbl_user 表并返回结果
	suc := dblayer.UserSignUp(username, encPasswd)
	if suc {
		c.JSON(http.StatusOK,
			gin.H{
				"code":    0,
				"msg":     "注册成功",
				"data":    nil,
				"forward": "/user/signin",
			})
	} else {
		c.JSON(http.StatusOK,
			gin.H{
				"code": 0,
				"msg":  "注册失败",
				"data": nil,
			})
	}

}

// SignInHandler 登录接口
func SignInHandler(c *gin.Context) {
	c.Redirect(http.StatusFound, "http://"+c.Request.Host+"/static/view/signin.html")
}

// DoSignInHandler : 登录接口
func DoSignInHandler(c *gin.Context) {
	username := c.Request.FormValue("username")
	passwd := c.Request.FormValue("password")
	encPasswd := util.Sha1([]byte(pwdSalt + passwd))

	// 1.校验用户名和密码
	pwdChecked := dblayer.UserSignIn(username, encPasswd)
	if !pwdChecked {
		c.JSON(http.StatusOK,
			gin.H{
				"code": 0,
				"msg":  "密码校验失败",
				"data": nil,
			})
		return
	}

	// 生成访问凭证（一般两种方式：1.token；2.cookies/session 浏览器端比较常见）这里选第一种
	token := GenToken(username)
	upRes := dblayer.UpdateToken(username, token)
	if !upRes {
		c.JSON(http.StatusOK,
			gin.H{
				"code": 0,
				"msg":  "登录失败",
				"data": nil,
			})
		return
	}

	// 登录成功后重定向到首页 并组装返回 username, token 重定向 url 等信息
	resp := util.RespMsg{
		Code: 0,
		Msg:  "OK",
		Data: struct {
			Location string
			Username string
			Token    string
		}{
			"http://" + c.Request.Host + "/static/view/home.html",
			username,
			token,
		},
	}

	c.Data(http.StatusOK, "octet-stream", resp.JSONToBytes())
}

// UserInfoHandler 查询用户信息
func UserInfoHandler(c *gin.Context) {
	// 1.解析请求参数
	username := c.Request.FormValue("username")
	// token := r.Form.Get("token")

	// 2.验证 token 是否有效  校验逻辑使用同一拦截器 HTTPInterceptor 处理
	// isTokenValid := IsTokenValid(token)
	// if !isTokenValid {
	// 	w.WriteHeader(http.StatusForbidden)
	// 	return
	// }

	// 查询用户信息
	user, err := dblayer.GetUserInfo(username)
	if err != nil {
		c.JSON(http.StatusForbidden,
			gin.H{})
		return
	}

	// 4. 组装并且响应用户数据
	resp := util.RespMsg{
		Code: 0,
		Msg:  "OK",
		Data: user,
	}

	c.Data(http.StatusOK, "octet-stream", resp.JSONToBytes())
}

// GenToken 生成用户token
func GenToken(username string) string {
	//token(40位字符 md5 后得到的32位字符再加上截图时间戳前8位）生成规则：md5(username+timestamp+tokenSalt)+timestamp[:8]
	ts := fmt.Sprintf("%x", time.Now().Unix())
	tokenPrefix := util.MD5([]byte(username + ts + tokenSalt))
	return tokenPrefix + ts[:8]
}

// IsTokenValid 验证 token 是否有效
func IsTokenValid(token string) bool {
	if len(token) != 40 {
		return false
	}

	// TODO:判断 token 的时效性，是否过期

	// TODO:从数据库表 tbl_user_token 查询 username 对应的 token 信息

	// TODO: 对比两个 token 是否一致

	return true
}

// UserExistsHandler ： 查询用户是否存在
func UserExistsHandler(c *gin.Context) {
	// 1. 解析请求参数
	username := c.Request.FormValue("username")

	// 3. 查询用户信息
	exists, err := dblayer.UserExist(username)
	if err != nil {
		c.JSON(http.StatusInternalServerError,
			gin.H{
				"msg": "server error",
			})
	} else {
		c.JSON(http.StatusOK,
			gin.H{
				"msg":    "ok",
				"exists": exists,
			})
	}
}
